package com.tbit.uqbike.webmanager.controller;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.NumberUtil;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.constant.SysConstant;
import com.tbit.uqbike.object.business.Point;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.MonitoringMachineExport;
import com.tbit.uqbike.object.pojo.dto.OperatingMachineDTO;
import com.tbit.uqbike.object.pojo.dto.OperatingMapMonitoringDTO;
import com.tbit.uqbike.object.pojo.vo.OperatingMapMachineStatus;
import com.tbit.uqbike.object.pojo.vo.OperatingMonitorV2VO;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.business.OperatingMapService;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import com.tbit.uqbike.webmanager.util.GeoUtil;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 车辆监控-运营地图
 *
 * @Author:BUGTian
 * @DATE: 2022/11/7
 */
@Validated
@RequestMapping("/operatingMap")
@RestController
public class OperatingMapController {

    @Autowired
    private OperatingMapService operatingMapService;
    @Autowired
    private AccountDao accountDao;


    /**
     * 车辆监控数据
     *
     * @param adAccountId 区域id
     * @param mapType     地图类型
     * @param regionIds   分区id 多个用,分割
     * @param machineType 车辆类型  0:电单车  1：单车
     * @return
     */
    @GetMapping("/operatingMapMonitoring")
    public Result<List<OperatingMapMachineStatus>> operatingMapMonitoring(Integer adAccountId, Integer mapType, String regionIds, Integer machineType) {
        if (adAccountId == null) {
            return Result.error("请选择区域");
        }
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        List<OperatingMapMachineStatus> operatingMapMachineStatusList = operatingMapService.operatingMapMonitoring(adAccountId, mapType, regionIds, machineType);
        return Result.success(operatingMapMachineStatusList);
    }


    /**
     * 车辆监控数据-新
     *
     * @param dto dto
     * @return Result
     */
    @PostMapping("/operatingMapMonitoringV2")
    public Result<Object> operatingMapMonitoringV2(@RequestBody OperatingMapMonitoringDTO dto) {
        Assert.notNull(dto.getAccountId(), "参数错误");
        return Result.success(operatingMapService.operatingMapMonitoringV2(dto));
    }

    /**
     * 车辆监控数据-新-分页
     *
     * @param dto dto
     * @return Result<PageResult < OperatingMonitorV2VO>>
     */
    @PostMapping("/operatingMapMonitoringV2Page")
    public Result<PageResult<OperatingMonitorV2VO>> operatingMapMonitoringV2Page(@RequestBody OperatingMapMonitoringDTO dto) {
        Assert.notNull(dto.getAccountId(), "参数错误");
        Assert.notNulls("缺少参数", dto.getPage(), dto.getSize());
        PageResult<OperatingMonitorV2VO> pageResult = operatingMapService.operatingMapMonitoringV2Page(dto);
        return Result.success(pageResult);
    }


    /**
     * 导出车辆监控数据-新
     *
     * @param dto dto
     * @return Result
     */
    @PostMapping("/exportOperatingMapMonitoringV2")
    public Result<Object> exportOperatingMapMonitoringV2(@RequestBody OperatingMapMonitoringDTO dto) {
        Assert.notNull(dto.getAccountId(), "参数错误");
        List<OperatingMonitorV2VO> operatingMonitorV2VOS = operatingMapService.operatingMapMonitoringV2(dto);
        ExcelUtil<OperatingMonitorV2VO> excel = new ExcelUtil<>(OperatingMonitorV2VO.class);
        JsonResult jsonResult = excel.exportExcel(operatingMonitorV2VOS, "车辆数据");
        return Result.success(jsonResult.getData());
    }


    /**
     * 分页查询车辆监控数据
     *
     * @param mapType             地图类型
     * @param page                当前页码
     * @param size                每页显示的行数
     * @param operatingMachineDTO .
     * @return
     */
    @GetMapping("/operatingMapMonitoringPage")
    public Result<PageResult<OperatingMapMachineStatus>> operatingMapMonitoringPage(Integer mapType,
                                                                                    Integer page, Integer size,
                                                                                    OperatingMachineDTO operatingMachineDTO) {
        final Integer adAccountId = operatingMachineDTO.getAdAccountId();
        if (adAccountId == null) {
            // 兼容前端
            return Result.success(new PageResult<>(1, 10, 0L, 0, new ArrayList<>()));
        }
        Assert.notNulls("缺少必要参数", adAccountId, page, size);
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        PageResult<OperatingMapMachineStatus> pageResult = operatingMapService.operatingMapMonitoringPage(mapType, page, size, operatingMachineDTO);
        return Result.success(pageResult);
    }

    /**
     * 导出车辆监控数据
     *
     * @param operatingMachineDTO .
     * @param mapType             地图类型
     * @return .
     */
    @GetMapping("/operatingMapMonitoringExport")
    public Result<Object> operatingMapMonitoringExport(Integer mapType, OperatingMachineDTO operatingMachineDTO) {
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        Account area = accountDao.getByAccountId(operatingMachineDTO.getAdAccountId());
        PageResult<OperatingMapMachineStatus> pageResult = operatingMapService.operatingMapMonitoringPage(mapType, 1, 65535,
                operatingMachineDTO);
        List<OperatingMapMachineStatus> list = pageResult.getList();
        for (OperatingMapMachineStatus operatingMapMachineStatus : list) {
            if (Objects.nonNull(operatingMapMachineStatus.getBatteryEu())) {
                operatingMapMachineStatus.setBatteryEuV(NumberUtil.div(operatingMapMachineStatus.getBatteryEu().intValue(), 1000, 3));
            }
        }
        ExcelUtil<OperatingMapMachineStatus> excelUtil = new ExcelUtil<>(OperatingMapMachineStatus.class);
        return Result.success(excelUtil.exportExcel(list, "_" + area.getName() + "_车辆列表").getData());
    }

    /**
     * 查询车辆状态
     *
     * @param machineId 车辆id
     * @return
     */
    @GetMapping("/queryMachineStatus")
    public Result<OperatingMapMachineStatus> queryMachineStatus(Integer machineId) {
        OperatingMapMachineStatus operatingMapMachineStatus = operatingMapService.queryMachineStatus(machineId);
        return Result.success(operatingMapMachineStatus);
    }

    /**
     * 根据围栏分页查询车辆监控数据
     *
     * @param pageNum   当前页码
     * @param pageSize  每页显示的行数
     * @param accountId 区域id
     * @param pointsStr 高德围栏
     */
    @GetMapping("/getMonitoringByPoints")
    public Result<PageResult<OperatingMapMachineStatus>> getMonitoringByPoints(@NotNull Integer accountId,
                                                                               @NotBlank(message = "请先圈选区域") String pointsStr,
                                                                               String userCode, @NotNull Integer pageNum,
                                                                               @NotNull Integer pageSize) {

        List<Point> points = GeoUtil.getPoints(pointsStr);
        Point point = new Point();
        List<OperatingMapMachineStatus> machineListDb = operatingMapService.getMonitoringByAccountId(accountId, 6, userCode);
        List<OperatingMapMachineStatus> machineList = machineListDb.stream()
                .filter(machine -> {
                    if (machine.getLonC() == null || machine.getLatC() == null) {
                        return false;
                    }
                    point.setX(machine.getLonC());
                    point.setY(machine.getLatC());
                    return GeoUtil.IsPtInPoly(point, points);
                })
                .collect(Collectors.toList());

        List<List<OperatingMapMachineStatus>> partition = ListUtil.partition(machineList, pageSize);

        PageResult<OperatingMapMachineStatus> result = new PageResult<>();
        if (CollectionUtils.isEmpty(partition)) {
            result.setList(new ArrayList<>());
        } else {
            result.setList(partition.get(pageNum - 1));
        }
        result.setPage(pageNum);
        result.setSize(pageSize);
        result.setTotal((long) machineList.size());
        return Result.success(result);
    }

    /**
     * 根据围栏导出车辆监控数据
     *
     * @param accountId 区域id
     * @param pointsStr 高德围栏点,英文逗号拼接
     */
    @GetMapping("/getMonitoringByPointsExport")
    public Result<Object> getMonitoringByPointsExport(@NotNull Integer accountId, @NotBlank(message = "请先圈选区域") String pointsStr) {

        List<Point> points = GeoUtil.getPoints(pointsStr);
        Point point = new Point();
        List<OperatingMapMachineStatus> machineListDb = operatingMapService.getMonitoringByAccountId(accountId, 6, null);
        List<MonitoringMachineExport> machineList = machineListDb.stream()
                .filter(machine -> {
                    if (machine.getLonC() == null || machine.getLatC() == null) {
                        return false;
                    }
                    point.setX(machine.getLonC());
                    point.setY(machine.getLatC());
                    return GeoUtil.IsPtInPoly(point, points);
                })
                .map(machine -> new MonitoringMachineExport(machine.getUserCode(), machine.getMachineNO(),
                        machine.getMachineType(), machine.getStateParse()))
                .collect(Collectors.toList());
        Account account = accountDao.getByAccountId(accountId);

        ExcelUtil<MonitoringMachineExport> excelUtil = new ExcelUtil<>(MonitoringMachineExport.class);
        return Result.success(excelUtil.exportExcel(machineList, "_" + account.getName() + "_车辆列表").getData());
    }
}
